package com.ljh.lottery.service.activitystatus.impl;

import com.ljh.lottery.common.errorcode.ServiceErrorCodeConstants;
import com.ljh.lottery.common.exception.ServiceException;
import com.ljh.lottery.service.ActivityService;
import com.ljh.lottery.service.activitystatus.ActivityStatusManager;
import com.ljh.lottery.service.activitystatus.operator.AbstractActivityOperator;
import com.ljh.lottery.service.dto.ConvertActivityStatusDTO;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author: Themberfue
 * @date: 2025/4/17 10:33
 * @description:
 */
@Component
public class ActivityStatusManagerImpl implements ActivityStatusManager {

    private static final Logger log = LoggerFactory.getLogger(ActivityStatusManagerImpl.class);

    @Autowired
    private final Map<String, AbstractActivityOperator> operatorMap = new HashMap<>();

    @Resource(name = "activityServiceImpl")
    ActivityService activityService;

    @Override
    @Transactional(rollbackFor = Exception.class) // ! 涉及多表操作，开启事务
    public void handlerEvent(ConvertActivityStatusDTO convertActivityStatusDTO) {
        // 1、活动状态扭转有依赖性，导致代码维护性差
        // 2、状态扭转条件可能会扩展，当前写法，扩展性差，维护性差

        // TODO 1. 校验处理事件是否为空
        if (CollectionUtils.isEmpty(operatorMap)) {
            log.warn("operatorMap 为空！");
        }

        // TODO 2. 按照一定的顺序处理状态扭转：责任链设计模式
        Map<String, AbstractActivityOperator> curMap = new HashMap<>(operatorMap);

        // TODO 2.1 先处理：人员、奖品...
        // TODO 2.2 后处理：活动...
        boolean update = processConvertStatus(curMap, convertActivityStatusDTO, 1);

        update = processConvertStatus(curMap, convertActivityStatusDTO, 2) || update;

        // TODO 3. 更新缓存
        if (update) {
            activityService.cacheActivity(convertActivityStatusDTO.getActivityId());
        }
    }

    @Override
    public void handlerRollbackEvent(ConvertActivityStatusDTO convertActivityStatusDTO) {
        // ? 奖品回滚到 INIT，活动必须回滚
        // TODO 1. 遍历责任链，回滚所有
        for (AbstractActivityOperator operator: operatorMap.values()) {
            operator.convert(convertActivityStatusDTO);
        }

        // TODO 2. 更新 Redis 缓存
        activityService.cacheActivity(convertActivityStatusDTO.getActivityId());
    }

    private Boolean processConvertStatus(Map<String, AbstractActivityOperator> curMap,
                                         ConvertActivityStatusDTO convertActivityStatusDTO,
                                         int sequence) {
        boolean update = false;

        // TODO 1. 遍历当前责任链
        Iterator<Map.Entry<String, AbstractActivityOperator>> iterator = curMap.entrySet().iterator();
        while (iterator.hasNext()) {
            AbstractActivityOperator operator = iterator.next().getValue();
            // TODO 1.1 校验处理顺序 | 是否需要扭转状态
            if (!operator.sequence().equals(sequence)
                    || !operator.needConvert(convertActivityStatusDTO)) {
                continue;
            }

            // TODO 1.2 扭转状态
            if (!operator.convert(convertActivityStatusDTO)) {
                log.error("{} 状态转换失败！", operator.getClass().getName());
                throw new ServiceException(ServiceErrorCodeConstants.ACTIVITY_STATUS_CONVERT_ERROR);
            }

            // TODO 1.3 从 iterator 删除当前 operator
            iterator.remove();
            update = true;
        }

        // TODO 2. 返回是否处理完成
        return update;
    }
}
